﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace fes
{
  //http://www.marketvolume.com/technicalanalysis/commodity_chanel_index.asp
  class CCI : Indicator, IIndicator
  {
    private int n = 0;
    private List<double> closePrices;
    private List<double> highPrices;
    private List<double> lowPrices;
    private double currentValue = -1;
    
    public CCI(Dictionary<String, Object> parameters) : base("CCI")
    {
      base.setInidicatorParams(parameters);
      n = (int) parameters["n"] + 1;
      closePrices = new List<double>();
      highPrices = new List<double>();
      lowPrices = new List<double>();
    }

    public override Indicator Clone()
    {
      Indicator r = new CCI(base.P);
      r.P = new Dictionary<string, object>();
      foreach (KeyValuePair<String, object> kvp in base.P)
        r.P.Add(kvp.Key, kvp.Value);
      foreach (FuzzySet fs in fuzzySets)
      {
        r.fuzzySets.Add(new FuzzySet(fs.Hedge, fs.name, fs.T));
      }
      return r;
    }

    public override void pushNextDayData(double open, double high, double low, double close, int vol)
    {
      closePrices.Add(close);
      highPrices.Add(high);
      lowPrices.Add(low);
      if (closePrices.Count > n)
      {
        closePrices.RemoveAt(0);
        highPrices.RemoveAt(0);
        lowPrices.RemoveAt(0);
      }
      calculateCCI();
    }

    public void setParameters(Dictionary<String, Object> parameters)
    {

        base.setInidicatorParams(parameters);
        n = (int)parameters["n"] + 1;
    }

    public override double getValue()
    {
      return currentValue;
    }

    private void calculateCCI()
    {
      if (closePrices.Count == n)  
      {
        int cnt = closePrices.Count;
        double smat = 0;   //simple moving average
        double meanDev = 0;  //simple moving average of abslute D values
        double[] tp = new double[cnt];
        
        double sum = 0;
        for (int i = 0; i < cnt; i++)
        {
          tp[i] = (closePrices[i] + highPrices[i] + lowPrices[i]) / 3.0;
          sum += tp[i];
        }
        smat = sum / cnt;

        sum = 0;
        for (int i = 0; i < cnt; i++)
        {
          sum += Math.Abs(smat - tp[i]);
        }
        meanDev = sum / cnt;

        currentValue = (tp[cnt - 1] - smat) * (0.015 * meanDev);
      }
      else
      {
        currentValue = -1;
      }
    }
  }
}
